#include "circlequeue.h"
#include <string.h>
#include "tools.h"

/*========================================================== 
    函数名 ：   CreateCircleQueue
    功能 ：		创建环形队列
    算法实现 ： <可选项> 
    参数说明 ： int     nMaxSize     [in]    环形队列最大长度
    返回值说明：NULL创建失败，否则返回队列地址（环形队列释放需要调用 DeleteCircleQueue方法）
    ------------------------------------------------------------------------------------------------------- 
    修改记录 ： 日 期 版本 修改人 走读人 修改记录
    1998/09/15 V1.0 某某（中文） 某某（中文） 记录关键内容
===========================================================*/
PCircleQueue CreateCircleQueue(int nMaxSize,int nWithMutex)
{
    // 如果最大长度小于1 直接返回失败
    if(nMaxSize < 1)
    {
        TRACE_DEBUG("invalid argument maxSize = %d",nMaxSize);
        return NULL;
    }

    // 创建环形队列
    PCircleQueue ptQueue = (PCircleQueue)malloc(sizeof(CircleQueue));
    if(NULL == ptQueue)
    {
        TRACE_DEBUG("malloc failed!");
        return ptQueue;
    }
    memset(ptQueue,0,sizeof(CircleQueue));
    if(1 == nWithMutex)
    {
        ptQueue->ptMutex = (PMutex)malloc(sizeof(Mutex));
        MUTEX_INIT(ptQueue->ptMutex);
    }

    // 初始化环形队列
    ptQueue->nMaxSize = nMaxSize;
    ptQueue->nNodeCnt = 0;
    return ptQueue;
}

/*========================================================== 
    函数名 ：   DeleteCircleQueue
    功能 ：		释放环形队列
    算法实现 ： <可选项> 
    参数说明 ： PCircleQueue     ptQueue     [in]    环形队列指针
    返回值说明：
    ------------------------------------------------------------------------------------------------------- 
    修改记录 ： 日 期 版本 修改人 走读人 修改记录
    1998/09/15 V1.0 某某（中文） 某某（中文） 记录关键内容
===========================================================*/
void DeleteCircleQueue(PCircleQueue ptQueue)
{
    if(NULL == ptQueue)
    {
        return ;
    }
    
    // 如果存在锁，加锁
    MUTEX_LOCK(ptQueue->ptMutex);

    // 释放节点
    PCircleQueueItem ptItem = ptQueue->ptHead;
    for(int i = 0; i < ptQueue->nNodeCnt ; ++i)
    {
        if(NULL == ptItem)
        {
            break;
        }
        PCircleQueueItem *ptNext = ptItem->pNext;
        free(ptItem);
        ptItem = ptNext;
    }

    // 释放锁
    MUTEX_DESTORY(ptQueue->ptMutex);
    free(ptQueue);
    return ;
}

/*========================================================== 
    函数名 ：   QueueExistsToken
    功能 ：		判断队列中是否存在此toke
    算法实现 ： <可选项> 
    参数说明 ： PCircleQueue     ptQueue     [in]    环形队列指针
                char*           paToken     [in]    token字符串
    返回值说明：0 不包含 1 包含
    ------------------------------------------------------------------------------------------------------- 
    修改记录 ： 日 期 版本 修改人 走读人 修改记录
    1998/09/15 V1.0 某某（中文） 某某（中文） 记录关键内容
===========================================================*/
int QueueExistsToken(PCircleQueue ptQueue,char *paToken)
{
    if(NULL == ptQueue
        || NULL == paToken)
    {
        return 0;
    }
    
    // 加锁
    MUTEX_LOCK(ptQueue->ptMutex);

    PCircleQueueItem ptItem = ptQueue->ptHead;
    while(ptItem != ptQueue->ptTail)
    {
        if(0 == strcmp(ptItem->achToken,paToken))
        {        
            // 释放锁
            MUTEX_UNLOCK(ptQueue->ptMutex);
            return 1;
        }
        ptItem = ptItem->pNext;
    }

    // 释放锁
    MUTEX_UNLOCK(ptQueue->ptMutex);
    return 0;
}

/*========================================================== 
    函数名 ：   AppendItem
    功能 ：		队列中添加数据
    算法实现 ： <可选项> 
    参数说明 ： PCircleQueue     ptQueue     [in]    环形队列指针
                char*           paToken     [in]    token字符串
    返回值说明：0 成功 1 失败（除非队列构筑失败，节点个数小于1，否则不会失败)
    ------------------------------------------------------------------------------------------------------- 
    修改记录 ： 日 期 版本 修改人 走读人 修改记录
    1998/09/15 V1.0 某某（中文） 某某（中文） 记录关键内容
===========================================================*/
int AppendItem(PCircleQueue ptQueue,char *paToken)
{
    if(NULL == ptQueue
        || NULL == paToken)
    {
        return 1;
    }

    MUTEX_LOCK(ptQueue->ptMutex);
    // 环形队列未满
    if(ptQueue->nNodeCnt < ptQueue->nMaxSize)
    {
        PCircleQueueItem ptItem = (PCircleQueueItem)malloc(sizeof(CircleQueueItem));
        memset(ptItem,0,sizeof(CircleQueueItem));
        strncpy(ptItem->achToken,paToken,POST_PARAM_VAL_BUF_LEN);
        ++ptQueue->nNodeCnt;
        // 第一个节点
        if(1 == ptQueue->nNodeCnt)
        {
            ptQueue->ptHead = ptItem;
            ptQueue->ptTail = ptItem;
        }
        else
        {
            ptQueue->ptTail->pNext = ptItem;
        }
        if(ptQueue->nNodeCnt == ptQueue->nMaxSize)
        {
            ptItem->pNext = ptQueue->ptHead;
        }
    }
    else    // 环形队列已经满了
    {
        PCircleQueueItem ptItem = ptQueue->ptTail->pNext;
        strncpy(ptItem->achToken,paToken,POST_PARAM_VAL_BUF_LEN);
        ptQueue->ptTail = ptItem;
        ptQueue->ptHead = ptItem->pNext;
    }
    MUTEX_UNLOCK(ptQueue->ptMutex);
    return 0;
}
